﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;


namespace Nocelab.MSCRM
{
    public class CRMHelper : IDisposable
    {
        private CrmService _crmService;
        private string _defaultCrmServer = "http://localhost:5555";
        private string _defaultOrganization = "MicrosoftCRM";
        private string _defaultUser = "Administrator";
        private string _defaultPass = "pass@word1";
        private string _defaultDomain = "litwareinc";
        public CRMHelper()
        {
            _crmService = Microsoft.Crm.Sdk.Utility.CrmServiceUtility.GetCrmService(_defaultCrmServer, _defaultOrganization, _defaultUser, _defaultPass, _defaultDomain);
        }

        public CRMHelper(string crmServerUrl, string organization)
        {
            _crmService = Microsoft.Crm.Sdk.Utility.CrmServiceUtility.GetCrmService(crmServerUrl, organization, _defaultUser, _defaultPass, _defaultDomain);
        }

        public CRMHelper(string crmServerUrl, string organization, string username, string password, string domain)
        {
            _crmService = Microsoft.Crm.Sdk.Utility.CrmServiceUtility.GetCrmService(crmServerUrl, organization, username, password, domain);
        }

        public bool TestCRMConnection(out string exceptionMessage)
        {
            bool testResult;
            exceptionMessage = "";
            testResult = true;
            try
            {
                //RetrieveVersionRequest versionRequest = new RetrieveVersionRequest();
                //RetrieveVersionResponse versionResponse = (RetrieveVersionResponse)_crmService.Execute(versionRequest);

                WhoAmIRequest whoRequest = new WhoAmIRequest();
                WhoAmIResponse whoResponse = (WhoAmIResponse)_crmService.Execute(whoRequest);

            }
            catch (Exception ex)
            {
                exceptionMessage = ex.Message;
                testResult = false;
            }

            return testResult;


        }
        
        /// <summary>
        ///  Import the specified memberid to a specified marketinglist
        /// </summary>
        /// <param name="entityId">MemberId</param>
        /// <param name="listId">MarketingListId</param>
        /// <returns></returns>
        public bool SingleAddMemberToList(Guid entityId, Guid listId, out string message)
        {
            message = "";
            AddMemberListRequest addRequest = new AddMemberListRequest();
            addRequest.EntityId = entityId;
            addRequest.ListId = listId;

            try
            {
                AddMemberListResponse response = (AddMemberListResponse)_crmService.Execute(addRequest);
                message = ""; // member correctly added to marketing list
                return true;
                
            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {   
                // there is a problem during the add
                message = ex.Detail.InnerText.ToString();
                return false;
            }

        }
        /// <summary>
        /// Import a member to a list
        /// </summary>
        /// <param name="memberType">Member type (represents the entity type of the record)</param>
        /// <param name="listId">Marketing List identification</param>
        /// <param name="memberName">Full name of the record</param>
        /// <param name="message">Return message</param>
        /// <returns></returns>
        public bool AddMemberToList(string memberType, Guid listId, string memberName, out string message)
        {
            bool retValue = false;
            String internalException = "";

            Guid entityId = GetEntityId(memberType, memberName);
            if (entityId == Guid.Empty || entityId == null)
            {
                message = "(Error)Member not found";
                retValue = false;
            }
            else
            {
                message = entityId.ToString(); // "entityId " + entityId;
                retValue = SingleAddMemberToList(entityId, listId, out internalException);
                if (!retValue)
                {
                    string sPattern = " With Id = .{8}-.{4}-.{4}-.{4}-.{12} Does Not Exist";
                    if (Regex.IsMatch(internalException, sPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase))
                    {
                        message = "(Error)This member type is not valid for the selected marketing list";
                    }
                    
                }
                retValue = true;
            }
            return retValue;
        }

        public BusinessEntity Query(string entityToFind, string attributeToControl, object[] _value)
        {

            QueryExpression query = new QueryExpression();
            query.EntityName = entityToFind;
            AllColumns columns = new AllColumns();
            query.ColumnSet = columns;



            FilterExpression filter = new FilterExpression();
            filter.FilterOperator = LogicalOperator.And;

            ConditionExpression condition = new ConditionExpression();
            condition.AttributeName = attributeToControl;
            condition.Operator = ConditionOperator.Equal;
            condition.Values = _value;

            filter.Conditions.Add(condition);
            query.Criteria = filter;
            RetrieveMultipleRequest request = new RetrieveMultipleRequest();
            request.Query = query;
            BusinessEntityCollection entity = null;
            query.PageInfo = new PagingInfo();
            query.PageInfo.Count = 10;
            query.PageInfo.PageNumber = 1;
            try
            {
                entity = _crmService.RetrieveMultiple(query);
                if (entity.BusinessEntities.Count > 0) 
                    return entity.BusinessEntities[0];

                else return null;
            }

            catch (Exception e)
            {
                return null;
            }
        }
        public BusinessEntityCollection QueryM(string entityToFind, string attributeToControl, object[] _value)
        {

            QueryExpression query = new QueryExpression();
            query.EntityName = entityToFind;
            AllColumns columns = new AllColumns();
            query.ColumnSet = columns;

            FilterExpression filter = new FilterExpression();
            filter.FilterOperator = LogicalOperator.And;

            ConditionExpression condition = new ConditionExpression();
            condition.AttributeName = attributeToControl;
            condition.Operator = ConditionOperator.Equal;
            condition.Values = _value;

            filter.Conditions.Add(condition);
            query.Criteria = filter;
            RetrieveMultipleRequest request = new RetrieveMultipleRequest();
            request.Query = query;
            BusinessEntityCollection entity = null;
            query.PageInfo = new PagingInfo();
            query.PageInfo.Count = 10;
            query.PageInfo.PageNumber = 1;
            try
            {
                entity = _crmService.RetrieveMultiple(query);
                return entity;
            }

            catch (Exception e)
            {
                return null;
            }
        }

        public BusinessEntityCollection QueryM(string entityToFind)
        {
            QueryExpression query = new QueryExpression();
            query.EntityName = entityToFind;
            AllColumns columns = new AllColumns();
            query.ColumnSet = columns;

            RetrieveMultipleRequest request = new RetrieveMultipleRequest();
            request.Query = query;
            BusinessEntityCollection entity = null;
            query.PageInfo = new PagingInfo();
            query.PageInfo.Count = 10;
            query.PageInfo.PageNumber = 1;
            try
            {
                entity = _crmService.RetrieveMultiple(query);
                return entity;
            }

            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }


        public BusinessEntityCollection QueryM(string entityToFind, out string exceptionMessage)
        {
            exceptionMessage = "";
            QueryExpression query = new QueryExpression();
            query.EntityName = entityToFind;
            AllColumns columns = new AllColumns();
            query.ColumnSet = columns;

            RetrieveMultipleRequest request = new RetrieveMultipleRequest();
            request.Query = query;
            BusinessEntityCollection entity = null;
            query.PageInfo = new PagingInfo();
            query.PageInfo.Count = 10;
            query.PageInfo.PageNumber = 1;
            try
            {
                entity = _crmService.RetrieveMultiple(query);
                return entity;
            }

            catch (Exception e)
            {
                exceptionMessage = e.Message;
                BusinessEntityCollection entity1 = new BusinessEntityCollection();

                return entity1;
                //return null;
            }
        }


        public ArrayList GetMarketingList()
        {
            string memberType ="";
            ArrayList mkList = new ArrayList();
            BusinessEntityCollection mlist = QueryM("list");
            for (int x = 0; x < mlist.BusinessEntities.Count; x++)
            {
                list mylist = (list)mlist.BusinessEntities[x];

                  
                switch (mylist.membertype.Value)
                {
                    case 1:
                        memberType = "account";
                        break;
                    case 2:
                        memberType = "contact";
                        break;
                    case 3:
                        memberType = "lead";
                        break;
                
                }

                mkList.Add(new string[] { mylist.listid.Value.ToString(), mylist.listname + "("+ memberType +")" });
            }
            return mkList;


        }

        /// <summary>
        /// Retrieve the record id of a record (of type: account, contact, lead) using the full name
        /// </summary>
        /// <param name="entityType">Entity type (possible values: account,contact, lead) </param>
        /// <param name="primaryAttributeValue">full name of the record</param>
        /// <returns></returns>
        public Guid GetEntityId(string entityType, string primaryAttributeValue)
        {
            Guid retGuid = Guid.Empty;
            switch (entityType)
            {
                case "account":
                    account myAccount = (account)Query(entityType, "name", new string[] { primaryAttributeValue });
                    if (myAccount != null)
                    {
                        retGuid = myAccount.accountid.Value;
                    }

                    break;

                case "lead":
                    lead myLead = (lead)Query(entityType, "fullname", new string[] { primaryAttributeValue });
                    if (myLead != null)
                    {
                        retGuid = myLead.leadid.Value;
                    }

                    break;

                case "contact":
                    contact myContact = (contact)Query(entityType, "fullname", new string[] { primaryAttributeValue });
                    if (myContact != null)
                    {
                        retGuid = myContact.contactid.Value;
                    }

                    break;
            }

            return retGuid;


        }



        #region IDisposable Members

        public void Dispose()
        {
            _crmService = null;
        }

        #endregion

    }
}
